use actix::{Actor, StreamHandler};
use actix_web::{HttpRequest, HttpResponse, web};
use actix_web_actors::ws;
use log::{debug, info};
use serde_json::Value;

use common::error::MyError;
use common::r::JsonResult;

struct MyWs;

impl Actor for MyWs {
    type Context = ws::WebsocketContext<Self>;

    /// 连接
    fn started(&mut self, _: &mut Self::Context) {
        info!("ws client connect!");
    }

    /// 断开连接
    fn stopped(&mut self, _: &mut Self::Context) {
        info!("ws client connect close!");
    }
}

impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for MyWs {
    fn handle(&mut self, item: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
        match item {
            Ok(ws::Message::Text(text)) => {
                debug!("client message: {}",text);
                //尝试序列化
                let json_message = serde_json::from_str::<Value>(&*text.to_string());
                match json_message{
                    Ok(json) => {
                        let json_res = JsonResult::ok(json);
                        let result = serde_json::to_string(&json_res);
                        ctx.text(result.unwrap());
                    }
                    Err(_) => {
                        let json_res = JsonResult::ok(text.to_string());
                        let result = serde_json::to_string(&json_res);
                        ctx.text(result.unwrap());
                    }
                }
            },
            Ok(ws::Message::Ping(msg)) => ctx.pong(&msg),
            Ok(ws::Message::Binary(bin)) => ctx.binary(bin),
            Ok(ws::Message::Close(reason)) => ctx.close(reason),
            _ => (),
        }
    }
}

pub async fn index(req: HttpRequest, stream: web::Payload) -> Result<HttpResponse, MyError> {
    let resp = ws::start(MyWs {}, &req, stream)?;
    Ok(resp)
}
